//
//  SpecialObservableViewController.swift
//  iOS-RxSwift-Tutorials_Example
//
//  Created by mengru.tian on 2020/9/18.
//  Copyright © 2020 CocoaPods. All rights reserved.
//

import UIKit
import RxSwift

//与数据相关的错误类型
enum DataError: Error {
    case cantParseJSON
}
//与缓存相关的错误类型
enum CacheError: Error {
    case failedCaching
}
//与缓存相关的错误类型
enum StringError: Error {
    case failedGenerate
}
class SpecialObservableViewController: UIViewController {

    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        title = "15.特征序列1：Single、Completable、Maybe"
        view.backgroundColor = .white
        
        // testSingle()
        // testSingle2()
        // testCompletable()
        testMaybe()
        // testMaybe2()
    }
    
    // Single 是 Observable 的另外一个版本。但它不像 Observable 可以发出多个元素，它要么只能发出一个元素，要么产生一个 error 事件。
    func testSingle() {
        let single = Single<[String: Any]>.create { single in
            let url = "https://douban.fm/j/mine/playlist?"
            + "type=n&channel=0&from=mainsite"
            let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _, error in
                if let error = error {
                    single(.error(error))
                    return
                }
                 
                guard let data = data,
                    let json = try? JSONSerialization.jsonObject(with: data,
                                                                 options: .mutableLeaves),
                    let result = json as? [String: Any] else {
                        single(.error(DataError.cantParseJSON))
                        return
                }
                 
                single(.success(result))
            }
             
            task.resume()
             
            return Disposables.create { task.cancel() }
        }
        
        single.subscribe { event in
            switch event {
            case .success(let json):
                print("JSON结果: ", json)
            case .error(let error):
                print("发生错误: ", error)
            }
        }
        .disposed(by: disposeBag)
        
        // 也可以使用 subscribe(onSuccess:onError:) 这种方式：
        single.subscribe(onSuccess: { json in
            print("JSON结果: ", json)
        }, onError: { error in
            print("发生错误: ", error)
        })
        .disposed(by: disposeBag)
    }

    // 我们可以通过调用 Observable 序列的 .asSingle() 方法，将它转换为 Single。
    func testSingle2() {
        Observable.of("1")
        .asSingle()
        .subscribe({ print($0) })
        .disposed(by: disposeBag)
    }
    
    // Completable 是 Observable 的另外一个版本。不像 Observable 可以发出多个元素，它要么只能产生一个 completed 事件，要么产生一个 error 事件。
    // 不会发出任何元素
    // 只会发出一个 completed 事件或者一个 error 事件
    // 不会共享状态变化
    func testCompletable() {
        let completable = Completable.create { completable in
            //将数据缓存到本地（这里掠过具体的业务代码，随机成功或失败）
            let success = (arc4random() % 2 == 0)
             
            guard success else {
                completable(.error(CacheError.failedCaching))
                return Disposables.create {}
            }
             
            completable(.completed)
            return Disposables.create {}
        }
        // 第一种方式订阅
        completable.subscribe { completable in
            switch completable {
            case .completed:
                print("保存成功!")
            case .error(let error):
                print("保存失败: \(error.localizedDescription)")
            }
        }
        .disposed(by: disposeBag)
        // 第二种方式订阅
        completable.subscribe(onCompleted: {
            print("保存成功!")
        }, onError: { error in
            print("保存失败: \(error.localizedDescription)")
        })
        .disposed(by: disposeBag)
    }

    // Maybe 同样是 Observable 的另外一个版本。它介于 Single 和 Completable 之间，它要么只能发出一个元素，要么产生一个 completed 事件，要么产生一个 error 事件。
    // 发出一个元素、或者一个 completed 事件、或者一个 error 事件
    // 不会共享状态变化
    func testMaybe() {
        let maybe = Maybe<String>.create { maybe in
             
            //成功并发出一个元素
            maybe(.success("hangge.com"))
             
            //成功但不发出任何元素
            maybe(.completed)
             
            //失败
            //maybe(.error(StringError.failedGenerate))
             
            return Disposables.create {}
        }
        // 第一种方式订阅
        maybe.subscribe { maybe in
            switch maybe {
            case .success(let element):
                print("执行完毕，并获得元素：\(element)")
            case .completed:
                print("执行完毕，且没有任何元素。")
            case .error(let error):
                print("执行失败: \(error.localizedDescription)")
            }
        }
        .disposed(by: disposeBag)
        // 第二种方式订阅
        maybe.subscribe(onSuccess: { element in
            print("执行完毕，并获得元素：\(element)")
        }, onError: { error in
            print("执行失败: \(error.localizedDescription)")
        }, onCompleted: {
            print("执行完毕，且没有任何元素。")
        })
        .disposed(by: disposeBag)
    }
    
    // 我们可以通过调用 Observable 序列的 .asMaybe() 方法，将它转换为 Maybe。
    func testMaybe2() {
        Observable.of("1")
        .asMaybe()
        .subscribe({ print($0) })
        .disposed(by: disposeBag)
    }
}
